package com.ruijie.acl.task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;

import com.ruijie.acl.AccessGroup;
import com.ruijie.acl.AclPlanParameters;
import com.ruijie.acl.TimeRange;
import com.ruijie.acl.service.AccessGroupService;
import com.ruijie.acl.service.AceService;
import com.ruijie.acl.service.AclDeviceService;
import com.ruijie.acl.service.AclInterfaceService;
import com.ruijie.acl.service.AclPlanParametersService;
import com.ruijie.acl.service.DeviceAccessGroupService;
import com.ruijie.acl.service.DeviceTimeRangeService;
import com.ruijie.acl.service.TimeRangeService;
import com.ruijie.acl.task.config.TaskConfigAclDevice;
import com.ruijie.acl.task.model.AccessGroupInfo;
import com.ruijie.acl.task.model.AclInterfaceInfo;
import com.ruijie.acl.task.model.TimeRangeInfo;
import com.ruijie.acl.type.InterfaceAccessGroupTypeEnum;
import com.ruijie.acl.utils.AclConfigUtil;
import com.ruijie.acl.utils.AclUtil;
import com.ruijie.acl.web.config.Constants;
import com.ruijie.batch.core.factory.SpringConfigAware;
import com.ruijie.batch.execution.BatchPlanExecution;
import com.ruijie.batch.plan.BatchPlan;
import com.ruijie.batch.plan.PlanDefinitionRequest;
import com.ruijie.batch.plan.PlanParameters;
import com.ruijie.batch.plan.items.ExtendPlanDefinitionRequest;
import com.ruijie.batch.plan.items.ExtendPlanDefinitionService;
import com.ruijie.batch.plan.items.ItemParameters;
import com.ruijie.batch.task.ItemProcessResult;
import com.ruijie.batch.task.event.PlanExecutionListener;
import com.ruijie.emp.batch.task.AbstractDeviceExtendTasklet;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.device.DeviceInterface;
import com.ruijie.emp.system.service.TelnetTemplateService;
import com.ruijie.foundation.exception.BusinessException;

/**
 * 
 * <p>
 * Title: 重新部署ACL组计划
 * </p>
 * <p>
 * Description: Function Description
 * </p>
 * <p>
 * Copyright: Copyright (c) 2009
 * </p>
 * <p>
 * Company: Ruijie Co., Ltd.
 * </p>
 * <p>
 * Create Time: 2009-09-27
 * </p>
 * <p>
 * Update Time:
 * </p>
 * <p>
 * Updater:
 * </p>
 * <p>
 * Update Comments:
 * </p>
 * 
 * @author ASAI
 */
public class ReDeployAccessGroup extends AbstractDeviceExtendTasklet implements SpringConfigAware,
		PlanExecutionListener {

	private Log logger = LogFactory.getLog(ReDeployAccessGroup.class);

	private TelnetTemplateService service;

	private AclPlanParametersService aclPlanParametersService;

	private AclInterfaceService aclInterfaceService;

	private AccessGroupService accessGroupService;

	private AceService aceService;

	private TimeRangeService timeRangeService;

	private TaskConfigAclDevice taskConfigAclDevice;

	private DeviceTimeRangeService deviceTimeRangeService;

	private ExtendPlanDefinitionService extendPlanDefinitionService;

	private DeviceAccessGroupService deviceAccessGroupService;

	private AclDeviceService aclDeviceService;

	private Map<String, String> paramMap = new HashMap<String, String>();

	protected Map<String, String> parseParameters(ItemParameters itemParameters) {
		return paramMap;
	}

	@SuppressWarnings("unchecked")
	public ItemProcessResult processItem(Object item, ItemParameters itemParameters) {
		ItemProcessResult result = new ItemProcessResult();
		paramMap.clear();
		Assert.notNull(item, "item is null");

		PlanParameters planParameters = new PlanParameters();

		AclPlanParameters aclPlanParamters = null;
		try {
			String aclPlanParamtersId = itemParameters
					.getParameterValue(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME);
			aclPlanParamters = aclPlanParametersService.get(Long.parseLong(aclPlanParamtersId));
		} catch (Exception ex) {
			throw new BusinessException("acl_deployment_initparam_error");
		}

		List<TimeRange> timeRangeList = null;
		List<AccessGroup> accessGroupList = null;
		List<AclInterfaceInfo> aclInterfaceInfoList = null;
		List<AclInterfaceInfo> aclInterfaceInfoLogList = null;


		if (!AclUtil.empty(aclPlanParamters.getAccessGroups())) {
			try {
				accessGroupList = accessGroupService.findByIds(aclPlanParamters.getAccessGroups());
				if (accessGroupList != null && accessGroupList.size() > 0) {
					// 转换组信息
					List<AccessGroupInfo> accessGroupInfoList = aceService
							.accessGroup2AccessGroupInfo(accessGroupList);
					planParameters.putParameter("accessGroupInfoList", accessGroupInfoList);

					this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_GROUPNAMES,
							AclConfigUtil.convertAccessGroupNames(accessGroupInfoList));
				}
				// 转换时间段信息
				if (!AclUtil.empty(aclPlanParamters.getTimeRanges())) {
					timeRangeList = timeRangeService.findByIds(aclPlanParamters.getTimeRanges());
				} else {
					if (accessGroupList != null && accessGroupList.size() > 0) {
						timeRangeList = timeRangeService.findByAccessGroup(accessGroupList);
					}
				}

				if (timeRangeList != null && timeRangeList.size() > 0) {
					List<TimeRangeInfo> timeRangeInfoList = AclConfigUtil
							.timeRangeList2TimeRangeInfoList(timeRangeList);
					planParameters.putParameter("timerangeInfoList", timeRangeInfoList);
					this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_TIMENAMES,
							AclConfigUtil.convertTimeRangeNames(timeRangeInfoList));
				}
				if (!AclUtil.empty(aclPlanParamters.getInterfaces())) {
					aclInterfaceInfoList = this.convertString2AclInterfaceInfo(aclPlanParamters
							.getInterfaces());
					aclInterfaceInfoLogList = this.convertString2AclInterfaceInfo(aclPlanParamters
							.getInterfacesLog());
					planParameters.putParameter("aclInterfaceInfoList", aclInterfaceInfoList);
					
					this.paramMap.put(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME_INTERFACES,
							AclConfigUtil.convertInterfaceStrings(aclInterfaceInfoLogList));
				}
			} catch (Exception ex) {
				throw new BusinessException("acl_deployment_initparam_error");
			}
			// 调用下发
			planParameters.putParameter("dealFlag", "modify");

			try {
				
				result = taskConfigAclDevice.processItem(item, planParameters);
				for (AccessGroup accessGroup : accessGroupList) {
					accessGroupService.saveSameWithAclDevice(accessGroup, aclDeviceService
							.getByDevice((Device) item), null);
					deviceAccessGroupService.updateChangedByAccessGroup(accessGroup, false,
							aclDeviceService.getByDevice((Device) item));
					if (!deviceAccessGroupService.existByAccessGroupAndChanged(accessGroup)) {
						accessGroupService.refresh(accessGroup);
						accessGroup.setIsChanged(false);
						accessGroupService.update(accessGroup);
					}
				}
			} catch (BusinessException e) {
				if (accessGroupList != null && accessGroupList.size() > 0) {
					for (AccessGroup accessGroup : accessGroupList) {
						try {
							if (deviceAccessGroupService.existByAccessGroupAndChanged(accessGroup)) {
								accessGroupService.refresh(accessGroup);
								accessGroup.setIsChanged(true);
								accessGroupService.update(accessGroup);
							}
						} catch (Exception ex) {
							//
						}
					}
				}
				throw e;
			}
			try {
				// 插入时间段和设备的关系。
				deviceTimeRangeService.addTimeRangeDevices(timeRangeList, (Device) item);
			} catch (Exception ex) {
				throw new BusinessException("acl_deployment_updatedatabase_error");
			}
		} else {
			logger.warn("要部署的组信息列表为空！");
		}

		return result;
	}

	/**
	 * 把字符串转换成计划接口类型
	 * 
	 * @param planInterfaceString
	 * @return
	 */
	private List<AclInterfaceInfo> convertString2AclInterfaceInfo(String planInterfaceString) {
		List<AclInterfaceInfo> aclInterfaceList = null;
		if (!AclUtil.empty(planInterfaceString)) {
			aclInterfaceList = new ArrayList<AclInterfaceInfo>();
			String[] arrAclPlanInterfaceList = planInterfaceString.split(";");
			for (String planInterfaceStr : arrAclPlanInterfaceList) {
				AclInterfaceInfo aclPlanInterface = new AclInterfaceInfo();
				String[] arrAclPlanInterface = planInterfaceStr.split(",");
				if (arrAclPlanInterface.length == 3) {
					DeviceInterface deviceInterface = aclInterfaceService.getDeviceInterface(Long
							.parseLong(arrAclPlanInterface[0]));
					aclPlanInterface.setIfName(deviceInterface.getName());

					AccessGroup accessGroup = aclInterfaceService.getAccessGroup(Long
							.parseLong(arrAclPlanInterface[2]));
					// 如果ACL组存在
					if (accessGroup != null) {
						String accessGroupType = arrAclPlanInterface[1];
						if (accessGroupType.equals(InterfaceAccessGroupTypeEnum.In.toString())) {
							aclPlanInterface.setInAccessGroupName(accessGroup.getName());

						} else if (accessGroupType.equals(InterfaceAccessGroupTypeEnum.Out
								.toString())) {
							aclPlanInterface.setOutAccessGroupName(accessGroup.getName());

						} else if (accessGroupType.equals(InterfaceAccessGroupTypeEnum.InOut
								.toString())) {
							aclPlanInterface.setInAccessGroupName(accessGroup.getName());
							aclPlanInterface.setOutAccessGroupName(accessGroup.getName());
						}
						aclInterfaceList.add(aclPlanInterface);
					}
				}
			}
		}
		return aclInterfaceList;
	}

	public void setService(TelnetTemplateService service) {
		this.service = service;
	}

	public void setAclInterfaceService(AclInterfaceService aclInterfaceService) {
		this.aclInterfaceService = aclInterfaceService;
	}

	public AclPlanParametersService getAclPlanParametersService() {
		return aclPlanParametersService;
	}

	public void setAclPlanParametersService(AclPlanParametersService aclPlanParametersService) {
		this.aclPlanParametersService = aclPlanParametersService;
	}

	public AccessGroupService getAccessGroupService() {
		return accessGroupService;
	}

	public void setAccessGroupService(AccessGroupService accessGroupService) {
		this.accessGroupService = accessGroupService;
	}

	public AceService getAceService() {
		return aceService;
	}

	public void setAceService(AceService aceService) {
		this.aceService = aceService;
	}

	public TimeRangeService getTimeRangeService() {
		return timeRangeService;
	}

	public void setTimeRangeService(TimeRangeService timeRangeService) {
		this.timeRangeService = timeRangeService;
	}

	public TaskConfigAclDevice getTaskConfigAclDevice() {
		return taskConfigAclDevice;
	}

	public void setTaskConfigAclDevice(TaskConfigAclDevice taskConfigAclDevice) {
		this.taskConfigAclDevice = taskConfigAclDevice;
	}

	public TelnetTemplateService getService() {
		return service;
	}

	public AclInterfaceService getAclInterfaceService() {
		return aclInterfaceService;
	}

	public DeviceTimeRangeService getDeviceTimeRangeService() {
		return deviceTimeRangeService;
	}

	public void setDeviceTimeRangeService(DeviceTimeRangeService deviceTimeRangeService) {
		this.deviceTimeRangeService = deviceTimeRangeService;
	}

	protected PlanDefinitionRequest prepareDefinitionRequest(BatchPlan selectedPlan) {
		PlanDefinitionRequest r = new ExtendPlanDefinitionRequest(selectedPlan);
		return r;
	}

	@Override
	public void after(BatchPlan plan, BatchPlanExecution bathcPlanExecution) {
		/*
		 * ExtendPlanDefinitionRequest request = (ExtendPlanDefinitionRequest)
		 * prepareDefinitionRequest(plan);
		 * request.setSessionCode("avdfd6778787");
		 * ((ExtendPlanDefinitionService) getExtendPlanDefinitionService())
		 * .populateExtendDefinitionRequest(request); Collection itemParameters =
		 * request.getItemParameters(); String id = ""; for (Object entry :
		 * itemParameters) { ItemParameters parameters = (ItemParameters)
		 * ((Object[]) entry)[1]; if (parameters == null) { parameters = new
		 * ItemParameters(); ((Object[]) entry)[1] = parameters; } id =
		 * parameters.getParameterValue(Constants.ACL_DEPLOY_PLAN_ITEM_PARAM_NAME);
		 *  }
		 * 
		 * AclPlanParameters aclPlanParamters = null; try{ aclPlanParamters =
		 * aclPlanParametersService.get(Long.parseLong(id)); }catch(Exception
		 * ex){ throw new BusinessException("acl_deployment_initparam_error"); }
		 * List<AccessGroup> accessGroupContrastList = null;
		 * accessGroupContrastList =
		 * accessGroupService.findByIds(aclPlanParamters.getAccessGroups()); if
		 * (accessGroupContrastList != null && accessGroupContrastList.size() >0 ){
		 * for(AccessGroup accessGroupPlan:accessGroupContrastList){ AccessGroup
		 * accessGroupSystem = accessGroupService.get(accessGroupPlan.getId());
		 * List<Ace> aceSystemList =
		 * aceService.getByAccessGroup(accessGroupSystem); List<Ace>
		 * acePlanList = aceService.getByAccessGroup(accessGroupPlan); if
		 * (aceSystemList.size() > 0 && aceSystemList.get(0) == null){
		 * aceSystemList.remove(0); } if (acePlanList.size() > 0 &&
		 * acePlanList.get(0) == null){ acePlanList.remove(0); } boolean
		 * hasSameAccessGroup = true; if
		 * (!accessGroupPlan.getAclType().equals(accessGroupSystem.getAclType())){
		 * hasSameAccessGroup = false; }else{ if (aceSystemList != null &&
		 * aceSystemList.size() > 0){ if (aceSystemList.size() !=
		 * acePlanList.size()){ hasSameAccessGroup = false; }else{ for (int
		 * aceIndex = 0; aceIndex < aceSystemList.size(); aceIndex++){ Ace
		 * tempAceSystem = aceSystemList.get(aceIndex);
		 * AclUtil.filterAce(tempAceSystem,accessGroupPlan.getAclType()); Ace
		 * tempAce = acePlanList.get(aceIndex);
		 * AclUtil.filterAce(tempAce,accessGroupPlan.getAclType()); if
		 * (!tempAceSystem.equals(tempAce)){ hasSameAccessGroup = false; break; } } }
		 * }else if (acePlanList.size() > 0){ hasSameAccessGroup = false; } } if
		 * (!hasSameAccessGroup){ accessGroupPlan.setIsChanged(true);
		 * accessGroupService.update(accessGroupPlan); } } }
		 */
	}

	@Override
	public void before(BatchPlan plan, BatchPlanExecution bathcPlanExecution) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onError(BatchPlan plan, BatchPlanExecution bathcPlanExecution, Throwable error) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onInterrupt(BatchPlan plan, BatchPlanExecution bathcPlanExecution) {
		// TODO Auto-generated method stub

	}

	public ExtendPlanDefinitionService getExtendPlanDefinitionService() {
		return extendPlanDefinitionService;
	}

	public void setExtendPlanDefinitionService(
			ExtendPlanDefinitionService extendPlanDefinitionService) {
		this.extendPlanDefinitionService = extendPlanDefinitionService;
	}

	public DeviceAccessGroupService getDeviceAccessGroupService() {
		return deviceAccessGroupService;
	}

	public void setDeviceAccessGroupService(DeviceAccessGroupService deviceAccessGroupService) {
		this.deviceAccessGroupService = deviceAccessGroupService;
	}

	public AclDeviceService getAclDeviceService() {
		return aclDeviceService;
	}

	public void setAclDeviceService(AclDeviceService aclDeviceService) {
		this.aclDeviceService = aclDeviceService;
	}

}
